﻿namespace HynuIOTA.Web.Areas.Blogs.Controllers
{
    using HynuIOTA.Common.Attribute;
    using HynuIOTA.Entity;
    using HynuIOTA.Entity.FormatEntity;
    using HynuIOTA.Entity.ViewEntitys;
    using HynuIOTA.Web.Filters;
    using HynuIOTA.Web.Models;
    using System;
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Web.Mvc;
    using static HynuIOTA.Common.StringConst;

    public class BlogController : BaseController
    {
        /// <summary>
        /// GET: Blogs/Blog
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        [SkipLogin]
        public ActionResult Index()
        {
            return Redirect(nameof(BlogList));
        }

        [SkipLogin]
        public ActionResult NavBar()
        {
            ViewBag.user = OpContext.UserEntity;
            return View();
        }

        /// <summary>
        /// GET: Blogs/Blog/BlogList
        /// 博客列表
        /// </summary>
        /// <param name="page"></param>
        /// <returns></returns>
        [HttpGet]
        [SkipLogin]
        [Route("~/Articles")]
        [Route("~/Articles/{page:int}.shtml", Name = "ArticleList")]
        [OutputCache(CacheProfile = "CacheFor10Min", VaryByParam = "page")]
        public async Task<ActionResult> BlogList(int page = 1)
        {
            var pageData = new PageData() { PageSize = 10, PageIndex = page };

            ViewBag.blogList = await (await OpContext.Service.BlogArticle.WherePageAsync(pageData, b => b.ApprovedPass == true, b => b.WriteTime, false)).ToListAsync();
            ViewBag.pageData = pageData;
            ViewBag.Title = "博客列表";
            return View("~/Areas/Blogs/Views/Blog/BlogList.cshtml");
        }

        /// <summary>
        /// GET: Blogs/Blog/UBlogList
        /// 用户博客列表
        /// </summary>
        /// <param name="id"></param>
        /// <param name="page"></param>
        /// <returns></returns>
        [HttpGet]
        [SkipLogin]
        public async Task<ActionResult> UBlogList(int? id, int page = 1)
        {
            if (id == null)
            {
                return OpContext.JsMsg(MODEL_VALIDATE_ERROR, Url.RouteUrl("ArticleList", new { page = 1 }));
            }

            var user = await OpContext.Service.User.Where(u => u.Id == id.Value).FirstOrDefaultAsync();
            if (user == null)
            {
                return OpContext.JsMsg(DATA_NOEXIST_ERROR, Url.RouteUrl("ArticleList", new { page = 1 }));
            }

            var pageData = new PageData() { PageSize = 10, PageIndex = page };
            ViewBag.blogList = await (await OpContext.Service.BlogArticle.WherePageAsync(pageData, b => b.ApprovedPass == true && b.UserId == id.Value, b => b.WriteTime, false)).ToListAsync();

            ViewBag.pageData = pageData;
            ViewBag.Title = $"{user.UserName} - 博客列表";

            return View(nameof(BlogList));
        }

        /// <summary>
        /// GET: Blogs/Blog/MyBlogList
        /// 我的博客列表页面
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ActionResult> MyBlogList(int page = 1)
        {
            var pageData = new PageData() { PageSize = 10, PageIndex = page };

            ViewBag.blogList = await (await OpContext.Service.BlogArticle.WherePageAsync(pageData, b => b.UserId == OpContext.UserEntity.Id, b => b.WriteTime, false)).ToListAsync();

            ViewBag.pageData = pageData;
            ViewBag.Title = $"我的博客列表";
            return View(nameof(BlogList));
        }

        /// <summary>
        /// ANY: Blogs/Blog/TagBlogList
        /// 某个标签下的博客列表
        /// </summary>
        /// <param name="id"></param>
        /// <param name="page"></param>
        /// <returns></returns>
        [SkipLogin]
        [OutputCache(CacheProfile = "CacheFor10Min", VaryByParam = "id,page")]
        public async Task<ActionResult> TagBlogList(int? id, int page = 1)
        {
            if (id == null)
            {
                return OpContext.JsMsg(MODEL_VALIDATE_ERROR, Url.RouteUrl("ArticleList", new { page = 1 }));
            }

            var tag = await OpContext.Service.Tags.Where(t => t.Id == id.Value).FirstOrDefaultAsync();
            if (tag == null)
            {
                return OpContext.JsMsg(DATA_NOEXIST_ERROR, Url.RouteUrl("ArticleList", new { page = 1 }));
            }

            var pageData = new PageData() { PageSize = 10, PageIndex = page };

            ViewBag.blogList = await (await OpContext.Service.BlogArticle.WherePageAsync(pageData, b => b.ApprovedPass == true && b.Tags.Any(t => t.Id == id.Value), b => b.WriteTime, false)).ToListAsync();

            ViewBag.pageData = pageData;
            ViewBag.Title = $"{tag.TagName}标签 - 博客列表";
            return View(nameof(BlogList));
        }

        /// <summary>
        /// GET: Blogs/Blog/ShowBlog
        /// 显示博客详情
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        [HttpGet]
        [SkipLogin]
        [Route("~/Article/{Id:int}.shtml", Name = "ShowArticle")]
        [OutputCache(CacheProfile = "CacheFor10Min", VaryByParam = "Id")]
        public async Task<ActionResult> ShowBlog(int? Id)
        {
            if (Id == null)
            {
                return OpContext.JsMsg(MODEL_VALIDATE_ERROR, Url.RouteUrl("ArticleList", new { page = 1 }));
            }

            var blog = await OpContext.Service.BlogArticle.Where(b => b.Id == Id.Value).FirstOrDefaultAsync();
            if (blog == null)
            {
                return OpContext.JsMsg(DATA_NOEXIST_ERROR, Url.RouteUrl("ArticleList", new { page = 1 }));
            }

            if (blog.ApprovedPass == false)
            {
                if (OpContext.UserEntity == null || OpContext.UserEntity.Id != blog.UserId)
                {
                    return OpContext.JsMsg(BLOG_NOPASS_ERROR, Url.RouteUrl("ArticleList", new { page = 1 }));
                }
            }

            var blogVisit = new BlogVisit()
            {
                BlogArticleId = blog.Id,
                IPAddress = Request.UserHostAddress
            };

            try
            {
                OpContext.Service.BlogVisit.Add(blogVisit);
                blog.VisitCount = blog.BlogVisit.Count;
                if (await OpContext.Service.SaveChangesAsync() < 1)
                {
                    // TODO: Re Log
                }
            }
            catch (Exception ex)
            {
                // TODO: Re Log
            }

            ViewBag.reCommend = await OpContext.Service
                .SqlQuery<BlogLinkViewModel>(
                    $"select TOP 5 Id,Title from BlogArticle where Id IN(select distinct [BlogArticle_Id] from dbo.BlogArticleTags where [Tags_Id] IN (select [Tags_Id] from dbo.BlogArticleTags where BlogArticle_Id = {blog.Id})) and Id <> {blog.Id}").ToListAsync();

            // TODO: 有时间思考一下如何通过函数式来进行推荐

            //var fist = OpContext.Service.Tags.Where(t => t.BlogArticle.Contains(blog));
            //var result = from t in fist
            //    from b in OpContext.Service.BlogArticle.Where(b => true)
            //    where b.Tags.Contains(t)
            //    select b;

            //var tagIds = OpContext.Service.Tags.Where(t => t.BlogArticle.Any(b => b.Id == id.Value)).Select(t => t.Id);
            //ViewBag.reCommend = await  OpContext.Service.BlogArticle.Where( b=> tagIds.Any(t => t == b.))

            ViewBag.isLogin = OpContext.UserEntity != null;
            ViewBag.blog = blog;

            return View("~/Areas/Blogs/Views/Blog/ShowBlog.cshtml");
        }

        /// <summary>
        /// GET: Blogs/Blog/AddBlog
        /// 添加博客页面
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ActionResult AddBlog()
        {
            return View();
        }

        /// <summary>
        /// POST: Blogs/Blog/AddBlog
        /// 添加博客
        /// </summary>
        /// <param name="blogForm"></param>
        /// <returns></returns>
        [HttpPost]
        [AjaxRequest]
        public async Task<ActionResult> AddBlog(BlogArticleViewModel blogForm)
        {
            if (ModelState.IsValid == false)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
            }

            if (OpContext.CheckValidateCode(blogForm.validateCode) == false)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATECODE_ERROR);
            }

            var blogArticle = new BlogArticle()
            {
                Title = blogForm.Title,
                Content = blogForm.Content,
                Summary = blogForm.Summary,
                image = blogForm.image,
                VisitCount = 0,
                CommentCount = 0,
                WriteTime = DateTime.Now,
                UserId = OpContext.UserEntity.Id,
                ApprovedPass = false
            };

            try
            {
                // 插入博客
                OpContext.Service.BlogArticle.Add(blogArticle);
                if (await OpContext.Service.SaveChangesAsync() < 1)
                {
                    return OpContext.JsonMsgErr(DATA_SAVECHANGES_ERROR);
                }

                // 建立关联
                foreach (var tagId in blogForm.Tags)
                {
                    var tag = await OpContext.Service.Tags.Where(t => t.Id == tagId).FirstOrDefaultAsync();
                    blogArticle.Tags.Add(tag);
                    tag.TagBlogCount = tag.BlogArticle.Count + 1;
                }

                if (await OpContext.Service.SaveChangesAsync() < 1)
                {
                    return OpContext.JsonMsgErr(DATA_SAVECHANGES_ERROR);
                }
            }
            catch (Exception ex)
            {
                OpContext.JsonMsgErr(ex.Message);
            }

            // 刷新缓存
            OpContext.RefreshCacheDependency(CacheDependencyKeys.Article);
            return OpContext.JsonMsgOK(DATA_ADD_SUCCESS);
        }

#region old code
        ///// <summary>
        ///// ANY: Blogs/Blog/DeleBlog
        ///// 删除博客
        ///// </summary>
        ///// <param name="id"></param>
        ///// <returns></returns>
        //public async Task<ActionResult> DeleBlog(int? id)
        //{
        //    if (id == null)
        //    {
        //        return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
        //    }

        //    try
        //    {
        //        OpContext.Service.BlogArticle.DeleteBy(b =>
        //            b.Id == id.Value && (b.User.Id == OpContext.UserEntity.Id));
        //        var result = await OpContext.Service.SaveChangesAsync();
        //        if (result == 0)
        //        {
        //            return OpContext.JsonMsgFail(DATA_NOEXIST_ERROR);
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        return OpContext.JsonMsgErr(ex.Message);
        //    }

        //    return OpContext.JsonMsgOK(DATA_DELECT_SUCCESS);
        //}

        ///// <summary>
        ///// GET: Blogs/Blog/EditBlog
        ///// 编辑博客
        ///// </summary>
        ///// <param name="id"></param>
        ///// <returns></returns>
        //[HttpGet]
        //public async Task<ActionResult> EditBlog(int? id)
        //{
        //    if (id == null)
        //    {
        //        return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
        //    }

        //    var blog = await OpContext.Service.BlogArticle
        //        .Where(b => b.Id == id.Value && b.UserId == OpContext.UserEntity.Id).FirstOrDefaultAsync();
        //    if (blog == null)
        //    {
        //        return OpContext.JsonMsgFail(DATA_NOEXIST_ERROR);
        //    }

        //    ViewBag.blog = blog;
        //    return View();
        //}

        ///// <summary>
        ///// ANY: Blogs/Blog/EditBlog
        ///// 编辑博客内容
        ///// </summary>
        ///// <param name="blogForm"></param>
        ///// <returns></returns>
        //[HttpPost]
        //public async Task<ActionResult> EditBlog(BlogArticleViewModel blogForm)
        //{
        //    if (ModelState.IsValid == false || blogForm.Id == null)
        //    {
        //        return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
        //    }

        //    if (OpContext.CheckValidateCode(blogForm.validateCode) == false)
        //    {
        //        return OpContext.JsonMsgFail(MODEL_VALIDATECODE_ERROR);
        //    }

        //    var uId = OpContext.UserEntity.Id;
        //    var blog = await OpContext.Service.BlogArticle
        //        .Where(b => b.Id == blogForm.Id.Value && b.UserId == uId).FirstOrDefaultAsync();
        //    if (blog == null)
        //    {
        //        return OpContext.JsonMsgFail(DATA_NOEXIST_ERROR);
        //    }

        //    blog.Title = blogForm.Title;
        //    blog.Content = blogForm.Content;
        //    blog.Summary = blogForm.Summary;
        //    blog.image = blogForm.image;
        //    blog.Tags.Clear();
        //    try
        //    {
        //        if (await OpContext.Service.SaveChangesAsync() < 1)
        //        {
        //            return OpContext.JsMsg(DATA_SAVECHANGES_ERROR);
        //        }

        //        // 建立关联
        //        foreach (var tagId in blogForm.Tags)
        //        {
        //            var tag = await OpContext.Service.Tags.Where(t => t.Id == tagId).FirstOrDefaultAsync();
        //            blog.Tags.Add(tag);
        //            tag.TagBlogCount = tag.BlogArticle.Count + 1;
        //        }

        //        if (await OpContext.Service.SaveChangesAsync() < 1)
        //        {
        //            return OpContext.JsonMsgErr(DATA_SAVECHANGES_ERROR);
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        return OpContext.JsonMsgErr(ex.Message);
        //    }

        //    return OpContext.JsonMsgOK(DATA_MODIFY_SUCCESS);
        //} 
#endregion

        /// <summary>
        /// ANY: Blogs/Blog/GetMyBlogList
        /// 我的博客列表
        /// </summary>
        /// <param name="paging"></param>
        /// <returns></returns>
        public async Task<ActionResult> GetMyBlogList(PagingViewModel paging)
        {
            // 验证字段是否通过
            if (ModelState.IsValid == false)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
            }

            // 构建pageData类
            var pageData = new PageData() { PageIndex = paging.page, PageSize = paging.rows };
            // 查询数据
            var result = await OpContext.Service.BlogArticle.WherePageAsync
            (
                pageData,
                b => b.UserId == OpContext.UserEntity.Id,
                b => b.WriteTime,
                false
            );
            var pageList = await result.Select(b => new { b.Id, b.Title, b.Tags, b.User.UserName, b.WriteTime }).ToListAsync();

            // 返回数据
            return OpContext.JsonMsgOK(data: new { tatol = pageData.RowCount, rows = pageList });
        }

        /// <summary>
        /// ANY: Blogs/Blog/GetBlogList
        /// 获取博客列表
        /// </summary>
        /// <param name="paging"></param>
        /// <returns></returns>
        public async Task<ActionResult> GetBlogList(PagingViewModel paging)
        {
            // 验证字段是否通过
            if (ModelState.IsValid == false)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
            }

            // 构建pageData类
            var pageData = new PageData() { PageIndex = paging.page, PageSize = paging.rows };
            // 查询数据
            var pageList = await OpContext.Service.BlogArticle.WherePage(
                pageData,
                b => b.ApprovedPass == true,
                b => b.WriteTime,
                false
            ).Select(b => new { b.Id, b.Title, b.Tags, b.User.UserName, b.WriteTime }).ToListAsync();

            // 返回数据
            return OpContext.JsonMsgOK(data: new { tatol = pageData.RowCount, rows = pageList });
        }

        /// <summary>
        /// ANY: /Blogs/Blog/GetNewCommentBlogList
        /// 获取最新评论的博客列表
        /// </summary>
        /// <returns></returns>
        [SkipLogin]
        [OutputCache(CacheProfile = "CacheFor10Min")]
        public async Task<ActionResult> GetNewCommentBlogList()
        {
            var list = await OpContext.Service.BlogArticle.Where(b => b.ApprovedPass == true).OrderByDescending(b => b.LastCommentTime)
                .Take(10).Select(b => new { b.Id, b.Title }).ToListAsync();
            return OpContext.JsonMsgOK(data: list);
        }

#region 博客评论管理

        /// <summary>
        /// ANY: Blogs/Blog/AddComment
        /// 添加评论
        /// </summary>
        /// <param name="blogCommentViewModel"></param>
        /// <returns></returns>
        [AjaxRequest]
        public async Task<ActionResult> AddComment(BlogCommentViewModel blogCommentViewModel)
        {
            if (ModelState.IsValid == false)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
            }

            if (OpContext.CheckValidateCode(blogCommentViewModel.validateCode) == false)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATECODE_ERROR);
            }

            var blogArticle = await OpContext.Service.BlogArticle.Where(b => b.Id == blogCommentViewModel.BlogArticleId).FirstOrDefaultAsync();
            if (blogArticle == null)
            {
                return OpContext.JsonMsgFail(DATA_NOEXIST_ERROR);
            }

            var blogComment = new BlogComment()
            {
                BlogArticleId = blogCommentViewModel.BlogArticleId,
                Content = blogCommentViewModel.Content,
                ReplyTime = DateTime.Now,
                UserId = OpContext.UserEntity.Id
            };

            try
            {
                OpContext.Service.BlogComment.Add(blogComment);
                blogArticle.LastCommentTime = blogComment.ReplyTime;
                blogArticle.CommentCount = blogArticle.BlogComment.Count;
                await OpContext.Service.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                return OpContext.JsonMsgFail(ex.Message);
            }

            return OpContext.JsonMsgOK(DATA_ADD_SUCCESS);
        }


        /// <summary>
        /// ANY: Blogs/Blog/GetCommentList
        /// 获取博客评论列表
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [SkipLogin]
        public async Task<ActionResult> GetCommentList(int? id)
        {
            if (id == null || ModelState.IsValid == false)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
            }
            var result = await OpContext.Service.BlogComment
                .Where(c => c.BlogArticleId == id.Value).OrderBy(c => c.ReplyTime)
                .Select(c => new { c.Id, c.BlogArticleId, c.ReplyTime, c.Content, c.User.UserName, c.UserId }).ToListAsync();
            return OpContext.JsonMsgOK(data: result);
        }

        /// <summary>
        /// ANY: Blogs/Blog/DeleComment
        /// 删除评论
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ActionResult> DeleComment(int? id)
        {
            if (id == null)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
            }

            try
            {
                OpContext.Service.BlogComment.DeleteBy(c => c.Id == id.Value && c.UserId == OpContext.UserEntity.Id);
                var result = await OpContext.Service.SaveChangesAsync();
                if (result == 0)
                {
                    return OpContext.JsonMsgFail(DATA_NOEXIST_ERROR);
                }
            }
            catch (Exception ex)
            {
                return OpContext.JsonMsgErr(ex.Message);
            }

            return OpContext.JsonMsgOK(DATA_DELECT_SUCCESS);
        }

        /// <summary>
        /// ANY: Blogs/Blog/GetBlogVisitCount
        /// 获取博客访问次数
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ActionResult> GetBlogVisitCount(int? id)
        {
            if (id == null)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
            }

            var count = await OpContext.Service.BlogVisit.Where(v => v.BlogArticleId == id.Value).CountAsync();

            return OpContext.JsonMsgOK(data: count);
        }
#endregion

#region 标签管理
        /// <summary>
        /// ANY: Blogs/Blog/AddTag
        /// 添加标签
        /// </summary>
        /// <param name="TagName"></param>
        /// <returns></returns>
        [AjaxRequest]
        public async Task<ActionResult> AddTag(string TagName)
        {
            if (TagName == null)
            {
                return OpContext.JsonMsgFail(MODEL_VALIDATE_ERROR);
            }

            var lowTag = TagName.ToLower();
            var result = await OpContext.Service.Tags.Where(t => t.TagName.ToLower() == lowTag).AnyAsync();
            if (result == true)
            {
                return OpContext.JsonMsgFail(DATA_EXIST_ERROR);
            }

            var tag = new Tags()
            {
                TagName = TagName,
                TagBlogCount = 0
            };
            try
            {
                OpContext.Service.Tags.Add(tag);
                if (await OpContext.Service.SaveChangesAsync() < 1)
                {
                    return OpContext.JsonMsgErr(DATA_SAVECHANGES_ERROR);
                }
            }
            catch (Exception ex)
            {
                return OpContext.JsonMsgErr(ex.Message);
            }

            // 刷新缓存
            OpContext.RefreshCacheDependency(CacheDependencyKeys.Tag);
            return OpContext.JsonMsgOK(DATA_ADD_SUCCESS);
        }

        /// <summary>
        /// ANY: Blogs/Blog/GetTags
        /// 获取标签列表
        /// </summary>
        /// <returns></returns>
        [SkipLogin]
        [AjaxRequest]
        [OutputCache(CacheProfile = "CacheFor10Min", VaryByParam = "count")]
        public async Task<ActionResult> GetTags(int? count)
        {
            List<Tags> tags;
            var result = OpContext.Service.Tags.Where(t => true).OrderByDescending(t => t.BlogArticle.Count);
            if (count != null)
            {
                tags = await result.Take(count.Value).ToListAsync();
            }
            else
            {
                tags = await result.ToListAsync();
            }

            return OpContext.JsonMsgOK(data: tags.Select(t => t.ToPOCO()));
        }

        /// <summary>
        /// ANY: Blogs/Blog/GetTagsCombox
        /// 获取标签Combox数据
        /// </summary>
        /// <returns></returns>
        [SkipLogin]
        [AjaxRequest]
        public async Task<ActionResult> GetTagsCombox()
        {
            var tags = await OpContext.Service.Tags.Where(t => true).Select(t => new ComboxJson() { id = t.Id, text = t.TagName, selected = false }).ToListAsync();
            return OpContext.JsonMsgOK(data: tags);
        }

        /// <summary>
        /// ANY: /Blogs/Blog/TagList
        /// 标签列表页面
        /// </summary>
        /// <returns></returns>
        [SkipLogin]
        public async Task<ActionResult> TagList()
        {
            var tags = await OpContext.Service.Tags.Where(t => true).OrderByDescending(t => t.TagBlogCount).ToListAsync();
            ViewBag.tags = tags;
            return View();
        }
    }
#endregion
}